package com.ruoyi.syf.service.impl;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.utils.TCPSocketUtil;
import com.ruoyi.common.utils.http.HttpUtils;
import com.ruoyi.syf.common.constant.EscalationConfigEnum;
import com.ruoyi.syf.common.constant.EscalationDataType;
import com.ruoyi.syf.domain.EscalationConfig;
import com.ruoyi.syf.domain.EscalationLog;
import com.ruoyi.syf.domain.TCPSocketEscalationData;
import com.ruoyi.syf.domain.TCPSocketEscalationDataRes;
import com.ruoyi.syf.service.EscalationService;
import com.ruoyi.syf.service.IEscalationConfigService;
import com.ruoyi.syf.service.IEscalationLogService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class EscalationServiceImpl implements EscalationService {

    @Resource
    private IEscalationConfigService configService;

    @Resource
    private IEscalationLogService logService;

    @Override
    public boolean socketEscalation(List<Map<String, Object>> data, String escalationType) {
        if (data.size() == 0) {
            return true;
        }
        //处理数据
        List<List<Map<String, Object>>> handleData = handleData(data, "2", escalationType);
        Map<String, String> map = getMap();
        for (List<Map<String, Object>> hData : handleData) {
            //构建上报数据
            TCPSocketEscalationData escalationData = buildTCPSocketEscalationData(JSONObject.toJSONString(hData), map, "ZF");
            String res = TCPSocketUtil.sendData(map.get(EscalationConfigEnum.HOST.getValue()),
                    Integer.valueOf(map.get(EscalationConfigEnum.PORT.getValue())),
                    JSON.toJSONString(escalationData) + "@@");
            TCPSocketEscalationDataRes dataRes = socketRes(res);
            //处理结果
            handleSocketRes(dataRes, escalationData.getDataId(), JSONObject.toJSONString(hData), escalationType);
        }
        return true;
    }

    @Override
    public boolean socketYQEscalation(List<Map<String, Object>> data, String escalationType) {
        Map<String, String> map = getMap();
        data.forEach(hData -> {
            //构建上报数据
            TCPSocketEscalationData escalationData = buildTCPSocketEscalationData(JSONObject.toJSONString(hData), map, "YQ");
            String res = TCPSocketUtil.sendData(map.get(EscalationConfigEnum.HOST_YQ.getValue()),
                    Integer.valueOf(map.get(EscalationConfigEnum.PORT_YQ.getValue())),
                    JSON.toJSONString(escalationData) + "@@");
            TCPSocketEscalationDataRes dataRes = socketRes(res);
            //处理结果
            handleSocketRes(dataRes, escalationData.getDataId(), JSONObject.toJSONString(hData), escalationType);
        });
        return true;
    }

    @Override
    public boolean httpEscalation(List<Map<String, Object>> data, String escalationType) {
        if (data.size() == 0) {
            return true;
        }
        //处理数据
        List<List<Map<String, Object>>> handleData = handleData(data, "1", escalationType);
        Map<String, String> map = getMap();
        handleData.forEach(hData -> {
            String res = HttpUtils.sendPost(map.get(EscalationConfigEnum.URL.getValue()), JSONObject.toJSONString(hData));
            JSONObject jsonObject = JSONObject.parseObject(res);
            //处理结果
            Integer code = jsonObject.getInteger("code");
            EscalationLog log;
            if (code == null || !code.equals(0)) {
                log = logService.buildErrEscalationLog(JSONObject.toJSONString(hData),
                        "1", escalationType, "请求失败", jsonObject.getString("message"));
            } else {
                log = logService.buildSucEscalationLog(JSONObject.toJSONString(hData), "1", escalationType);
            }
            logService.save(log);
        });
        return true;
    }

    @Override
    public boolean reEscalation(Long id) throws IllegalAccessException {
        EscalationLog log = logService.getById(id);
        String escalationType = log.getEscalationType();
        if (escalationType.equals(EscalationDataType.REAL_TIME.getCode()) || escalationType.equals(EscalationDataType.ALARM.getCode())) {
            reTCPSocket(log, "YQ");
        } else {
            String type = log.getType();
            if (type.equals("1")) {
                reHttp(log);
            } else {
                reTCPSocket(log, "ZF");
            }
        }
        return true;
//        EscalationLog log = logService.getById(id);
//        String escalationType = log.getEscalationType();
//        if (escalationType.equals(EscalationDataType.REAL_TIME.getCode()) || escalationType.equals(EscalationDataType.ALARM.getCode())) {
//            reTCPSocket(log, "YQ");
//        } else {
//            String type = log.getType();
//            String data = log.getData();
//            List<Map> dataList = JSON.parseArray(data, Map.class);
//            Object entId = dataList.get(0).get("ENT_ID");
//            if (entId != null) {
//                //因配置原因未进行上报
//                String companyCode = configService.getCompanyCode(entId.toString());
//                if (companyCode == null) {
//                    throw new IllegalAccessException("企业编码未完善");
//                }
//                dataList.forEach(item -> {
//                    item.remove("ENT_ID");
//                    item.put(EscalationConfigEnum.COMPANY_CODE.getValue(), companyCode);
//                });
//                String hData = JSONObject.toJSONString(dataList);
//                log.setData(hData);
//            }
//            if (type.equals("1")) {
//                reHttp(log);
//            } else {
//                reTCPSocket(log, "ZF");
//            }
//        }
//        return true;
    }

    /**
     * http重新上报
     *
     * @param log 上报日志
     */
    private void reHttp(EscalationLog log) {
        Map<String, String> map = getMap();
        String res = HttpUtils.sendPost(map.get(EscalationConfigEnum.URL.getValue()), log.getData());
        JSONObject jsonObject = JSONObject.parseObject(res);
        //处理结果
        Integer code = jsonObject.getInteger("code");
        if (code == null || !code.equals(0)) {
            log.setError("请求失败");
            log.setMessage(jsonObject.getString("message"));
        } else {
            log.setStatus(true);
            log.setError(null);
            log.setMessage(null);
        }
        logService.updateById(log);
    }

    /**
     * TCP重新上报
     *
     * @param log     上报日志
     * @param tcpType tcp类型（ZH：政府，YQ：园区）
     */
    private void reTCPSocket(EscalationLog log, String tcpType) {
        Map<String, String> map = getMap();
        String data = log.getData();
        //构建上报数据
        TCPSocketEscalationData escalationData = buildTCPSocketEscalationData(JSONObject.toJSONString(data), map, tcpType);
        String res;
        if (tcpType.equals("ZF")) {
            res = TCPSocketUtil.sendData(map.get(EscalationConfigEnum.HOST.getValue()),
                    Integer.valueOf(map.get(EscalationConfigEnum.PORT.getValue())),
                    JSON.toJSONString(escalationData) + "@@");
        } else {
            res = TCPSocketUtil.sendData(map.get(EscalationConfigEnum.HOST_YQ.getValue()),
                    Integer.valueOf(map.get(EscalationConfigEnum.PORT_YQ.getValue())),
                    JSON.toJSONString(escalationData) + "@@");
        }
        TCPSocketEscalationDataRes dataRes = socketRes(res);
        //处理结果
        if (dataRes != null && dataRes.getSuccess()) {
            if (escalationData.getDataId().equals(dataRes.getDataId())) {
                log.setStatus(true);
                log.setError(null);
                log.setMessage(null);
            }
        } else {
            if (dataRes == null) {
                log.setError("请求失败");
            } else {
                log.setError(dataRes.getError().toString());
                log.setMessage(dataRes.getMessage());
            }
        }
        logService.updateById(log);
    }

    /**
     * 获取配置集合并转化为map(排除企业编码)
     */
    private Map<String, String> getMap() {
        List<EscalationConfig> ridOfCompanyCode = configService.getRidOfCompanyCode();
        Map<String, String> map = new HashMap<>();
        ridOfCompanyCode.forEach(item -> {
            map.put(item.getConfigKey(), item.getConfigValue());
        });
        return map;
    }

    /**
     * 处理上报数据
     *
     * @param data           数据集
     * @param type           上报类型(1:http;2:Socket;)
     * @param escalationType 上报数据类型
     */
    private List<List<Map<String, Object>>> handleData(List<Map<String, Object>> data, String type, String escalationType) {
        EscalationConfig companyCode = configService.getCompanyCode();
        List<List<Map<String, Object>>> resData = new ArrayList<>();//返回数据
        List<EscalationLog> logData = new ArrayList<>();//日志数据
        data.forEach(map -> {
            map.put(EscalationConfigEnum.COMPANY_CODE.getValue(), companyCode);
        });
        resData.add(data);
        //新增失败日志
        logService.saveBatch(logData);
        return resData;
        //        List<EscalationConfig> companyCodes = configService.getCompanyCode();
//        List<List<Map<String, Object>>> resData = new ArrayList<>();//返回数据
//        List<EscalationLog> logData = new ArrayList<>();//日志数据
//        //以企业分组
//        Map<Object, List<Map<String, Object>>> entIdCollect = data.stream().collect(Collectors.groupingBy(item -> item.get("ENT_ID")));
//        for (Object entId : entIdCollect.keySet()) {
//            List<Map<String, Object>> maps = entIdCollect.get(entId);
//            //判断相关企业是否已完善企业编码
//            String companyCode = null;
//            for (EscalationConfig config : companyCodes) {
//                if (entId.equals(config.getFirmId())) {
//                    String value = config.getConfigValue();
//                    if (value != null && !value.isEmpty()) {
//                        companyCode = value;
//                        break;
//                    }
//                }
//            }
//            if (companyCode != null) {
//                String finalCompanyCode = companyCode;
//                maps.forEach(map -> {
//                    map.remove("ENT_ID");
//                    map.put(EscalationConfigEnum.COMPANY_CODE.getValue(), finalCompanyCode);
//                });
//                resData.add(maps);
//            } else {
//                logData.add(logService.buildErrEscalationLog(JSONObject.toJSONString(maps),
//                        type, escalationType, null, null));
//            }
//        }
//        //新增失败日志
//        logService.saveBatch(logData);
//        return resData;
    }

    /**
     * 构建TCPSocket上报数据
     *
     * @param data    原始数据
     * @param map     配置数据
     * @param tcpType tcp类型（ZH：政府，YQ：园区）
     * @return TCPSocket上报数据
     */
    public TCPSocketEscalationData buildTCPSocketEscalationData(String data, Map<String, String> map, String tcpType) {
        TCPSocketEscalationData escalationData = new TCPSocketEscalationData();
        String secretKey;
        if (tcpType.equals("ZF")) {
            escalationData.setAppId(map.get(EscalationConfigEnum.APP_ID.getValue()));
            escalationData.setServiceId(map.get(EscalationConfigEnum.SERVICE_ID.getValue()));
            secretKey = map.get(EscalationConfigEnum.SECRET_KEY.getValue());
        } else {
            escalationData.setAppId(map.get(EscalationConfigEnum.APP_ID_YQ.getValue()));
            escalationData.setServiceId(map.get(EscalationConfigEnum.SERVICE_ID_YQ.getValue()));
            secretKey = map.get(EscalationConfigEnum.SECRET_KEY_YQ.getValue());
        }
        UUID uuid = UUID.randomUUID();
        escalationData.setDataId(uuid.toString());
        //加密
        escalationData.setData(TCPSocketUtil.encrypt(data, secretKey));
        return escalationData;
    }

    /**
     * 处理TCPSocket上报结果日志
     *
     * @param dataRes        返回数据
     * @param dataId         数据标识ID
     * @param data           数据
     * @param escalationType 上报数据类型
     */
    public void handleSocketRes(TCPSocketEscalationDataRes dataRes, String dataId, String data, String escalationType) {
        EscalationLog log = null;
        if (dataRes != null && dataRes.getSuccess()) {
            if (dataId.equals(dataRes.getDataId())) {
                log = logService.buildSucEscalationLog(JSONObject.toJSONString(data), "2", escalationType);
            }
        } else {
            if (dataRes == null) {
                log = logService.buildErrEscalationLog(JSONObject.toJSONString(data), "2",
                        escalationType, "请求失败", null);
            } else {
                log = logService.buildErrEscalationLog(JSONObject.toJSONString(data), "2",
                        escalationType, dataRes.getError().toString(), dataRes.getMessage());
            }
        }
        if (log != null) {
            logService.save(log);
        }
    }

}
